package vim.meet.javassist;

import javassist.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class ReplaceClassFileTransformer implements ClassFileTransformer {
    
    private static final Logger logger = LoggerFactory.getLogger(ReplaceClassFileTransformer.class);

    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
//        System.out.println(className);//sun/launcher/LauncherHelper
        logger.info(className);
//      全限定名称转换: sun/launcher/LauncherHelper -->sun.launcher.LauncherHelper
      if (className != null && className.indexOf("/") != -1) {
          className = className.replaceAll("/", ".");
      }
        if (className.endsWith("ReplaceA")) {
            logger.info("ReplaceA");
            logger.info(className);
            try {
                CtClass cc = ClassPool.getDefault().get(className);
                CtMethod method = cc.getDeclaredMethod("replace");
                method.setBody("{System.out.println(\"replace body\");}");
                try {
                    return cc.toBytecode();
                } catch (IOException e) {
                    logger.error(e.getMessage(), e);
                } catch (CannotCompileException e) {
                    logger.error(e.getMessage(), e);
                }
            } catch (NotFoundException e) {
                logger.error(e.getMessage(), e);
            } catch (CannotCompileException e) {
                logger.error(e.getMessage(), e);
            }
        }
        
        if(className.endsWith("ReplaceB")){
            logger.info("ReplaceB");
            CtClass cc = null;
            try {
                logger.info(className);
                cc = ClassPool.getDefault().get(className);
            } catch (NotFoundException e) {
                logger.error(e.getMessage(), e);
            }
            assert cc != null;
            try {
                CtMethod m = cc.getDeclaredMethod("replace");
                m.insertBefore("System.out.println(\"classFileTransformer\");");
//                m.insertAfter("System.out.println(\"classFileTransformer\");");
            } catch (NotFoundException e) {
                logger.error(e.getMessage(), e);
            } catch (CannotCompileException e) {
                logger.error(e.getMessage(), e);
            }finally{
                if(cc != null)
                    try {
                        return cc.toBytecode();
                    } catch (IOException | CannotCompileException e) {
                        logger.error(e.getMessage(), e);
                    }
            }
        }
        
        return null;
    }
    
    public static void premain(String options, Instrumentation instrumentation) {
        System.out.println("options:"+options);
        //注册我自己的字节码转换器
        instrumentation.addTransformer(new ReplaceClassFileTransformer());
        instrumentation.getObjectSize(logger);
    }
    
    public static void main(String[] args) {
        
    }
    
}
